﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Tao.FreeGlut;
using Tao.OpenGl;
using Tarea2Raytracing;
using SceneLib;

namespace Tarea1
{
    class Program
    {
        private static int WIDTH = 300;
        private static int HEIGHT = 300;

        private static int mode = 1;
        
        private static OpenGLRenderer openGLrenderer;
        private static RaytraceRenderer raytraceRenderer;
        private static Scene scene;

         static void Main(string[] args)
         {
             Glut.glutInit();
             Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB);

             Glut.glutInitWindowSize(WIDTH, HEIGHT);
             Glut.glutInitWindowPosition(100, 100);
             Glut.glutCreateWindow("Tarea 1");
  
             Init();
  
             Glut.glutDisplayFunc(new Glut.DisplayCallback(Draw));
             Glut.glutIdleFunc(new Glut.IdleCallback(Update));

             Glut.glutKeyboardFunc(new Glut.KeyboardCallback(KeyboardHandle));
  
             Glut.glutMainLoop();
  
         }
  
         static void Init()
         {
             scene = new Scene(WIDTH, HEIGHT);
             scene.Load("MyCornellBox.xml");
             openGLrenderer = new OpenGLRenderer(scene, WIDTH, HEIGHT);
             raytraceRenderer = new RaytraceRenderer(scene, WIDTH, HEIGHT);
         }

         static void Draw()
         {
             if (mode == 1)
             {
                 openGLrenderer.Render();
             }
             else if (mode == 2)
             {
                 raytraceRenderer.Render();
             }
         }

         static void Update()
         {
             if (mode == 2)
             {
                 raytraceRenderer.Update();
             }
         }

         static void KeyboardHandle(byte key, int x, int y)
         {
             SceneCamera sceneCam = scene.Camera;
             Vector dir = sceneCam.Target - sceneCam.Position;
             float tar_posDist = dir.Magnitude3();
             dir.Normalize3();
             Vector right = Vector.Cross3(dir, sceneCam.Up);
             float camSpeed = 10f;
             Vector tempVec;
             float turnSpeed = 0.01f;

             if (key == 49)
             {
                 mode = 1;
                 Glut.glutPostRedisplay();
             }
             else if (key == 50)
             {
                 mode = 2;
                 raytraceRenderer.ResetTracer();
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'w')
             {
                 scene.Camera.Position += dir * camSpeed;
                 scene.Camera.Target += dir * camSpeed;
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'s')
             {
                 scene.Camera.Position -= dir * camSpeed;
                 scene.Camera.Target -= dir * camSpeed;
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'a')
             {
                 scene.Camera.Position -= right * camSpeed;
                 scene.Camera.Target -= right * camSpeed;
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'d')
             {
                 scene.Camera.Position += right * camSpeed;
                 scene.Camera.Target += right * camSpeed;
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'i')
             {
                 tempVec = dir + scene.Camera.Up * turnSpeed;
                 tempVec.Normalize3();
                 scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                 scene.Camera.Up = Vector.Cross3(right, tempVec);
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'k')
             {
                 tempVec = dir - scene.Camera.Up * turnSpeed;
                 tempVec.Normalize3();
                 scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                 scene.Camera.Up = Vector.Cross3(right, tempVec);
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'j')
             {
                 tempVec = dir - right * turnSpeed;
                 tempVec.Normalize3();
                 scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                 Glut.glutPostRedisplay();
             }
             else if (key == (byte)'l')
             {
                 tempVec = dir + right * turnSpeed;
                 tempVec.Normalize3();
                 scene.Camera.Target = scene.Camera.Position + tempVec * tar_posDist;
                 Glut.glutPostRedisplay();
             }
         }
    }
}
